package com.anxin.act.process.service;

import com.alibaba.fastjson.JSONObject;
import com.anxin.act.busFlow.dao.WfBusNodeDao;
import com.anxin.act.busFlow.dao.WfConfigNodeDao;
import com.anxin.act.busFlow.entity.WfBusNode;
import com.anxin.act.busFlow.entity.WfBusNodeEvolve;
import com.anxin.act.busFlow.entity.WfBusRound;
import com.anxin.act.busFlow.entity.WfConfigNode;
import com.anxin.act.busFlow.inter.SwitchBusStatus;
import com.anxin.act.busFlow.service.WfBusNodeEvolveService;
import com.anxin.act.busFlow.service.WfBusNodeService;
import com.anxin.act.busFlow.service.WfBusRoundService;
import com.anxin.act.busFlow.service.WfConfigNodeService;
import com.anxin.act.process.dao.ActProcessDao;
import com.anxin.act.process.inter.ProcessEnd;
import com.anxin.act.task.service.ActTaskService;
import com.anxin.act.task.vo.TaskVo;
import com.anxin.act.utils.ActTaskUtils;
import com.anxin.act.utils.ActUtils;
import com.anxin.common.utils.DateUtils;
import com.anxin.common.utils.LogUtils;
import com.anxin.common.utils.StringUtils;
import com.anxin.common.utils.dict.DictUtils;
import com.anxin.common.utils.sys.UserUtils;
import com.anxin.desform.service.EnhanceService;
import com.anxin.desform.service.OnlineServer;
import com.anxin.framework.redis.MqProducer;
import com.anxin.framework.redis.RedisMq;
import com.anxin.sys.message.utils.SendMessageUtils;
import com.anxin.sys.system.entity.SysUser;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author: liuxiangyu
 * @date: 2020/5/22 18:16
 */
@Service
public class ProcessEndService implements RedisMq {

    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private ActProcessDao actProcessDao;
    @Autowired
    private MqProducer mqProducer;
    @Autowired
    private HistoryService historyService;
    @Autowired
    ApplicationContext context;
    @Autowired
    private WfBusNodeService wfBusNodeService;
    @Autowired
    private WfConfigNodeDao wfConfigNodeDao;
    @Autowired
    private WfBusNodeDao wfBusNodeDao;
    @Autowired
    private EnhanceService enhanceService;
    @Autowired
    private OnlineServer onlineServer;
    @Autowired
    private WfBusNodeEvolveService wfBusNodeEvolveService;
    @Autowired
    private WfBusRoundService wfBusRoundService;


    /**
     * 判断流程是否已经结束
     * @param actId 流程实例ID
     */
    public void whetherToEnd(String actId){
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(actId).singleResult();
        List<Task> currentTaskList = ActTaskUtils.getCurrentTaskList(actId);

        Map<String, Object> processVar = ActUtils.getProcessVar(actId);
        if (processInstance == null || currentTaskList.size() == 0){
            // 如果结束过则不在重复调用
            if (!"true".equals(processVar.get("actProcessEnd"))){
                mqProducer.sendMessage(ProcessEndService.class,actId);
            }
            //this.processEnd(taskVo);
        }

        // 判断任务是否为结束节点，如果是则调用流程结束的任务
        if (!"true".equals(processVar.get("actProcessEnd"))){
            for (Task task : currentTaskList) {
                ActivityImpl activityImpl = ActUtils.getActivityImpl(task);
                if ("true".equals(activityImpl.getProperties().get("endtasknode"))) {
                    runtimeService.setVariable(actId,"actProcessEnd","true");
                    mqProducer.sendMessage(ProcessEndService.class,actId);
                    return;
                }
            }
        }


    }

    /**
     * 流程结束后修改流程状态
     * @param dataTable 业务表名
     * @param dataId 业务ID
     * @param dataId 获取流程结束状态 (正常审批完成或审批终止)
     */
    public void updateEndStatus(String dataTable,String dataId,String status){

        actProcessDao.updateDataTable(dataTable,dataId,status,null);
    }


    /**
     * 获取流程结束状态 (正常审批完成或审批终止)
     * @param actId 流程实例ID
     * @return
     */
    public String getActEndStatus(String actId){
        String status = "W";
        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().processInstanceId(actId).activityType("endEvent").orderByHistoricActivityInstanceStartTime().asc().list();
        for (HistoricActivityInstance historicActivityInstance : list) {
            ActivityImpl activityImpl = ActUtils.getActivityImpl(historicActivityInstance.getProcessDefinitionId(), historicActivityInstance.getActivityId());
            // 如果结束节点的描述信息为 abnormalend 则将流程状态改为审批终止
            if ("abnormalend".equals(activityImpl.getProperty("documentation"))) {
                status = "Z";
            }
        }

        return status;
    }



    /**
     * 流程结束消费者
     * @param actId 流程实例ID
     * @return
     */
    @Override
    public boolean onMessage(String actId) {

        // 更新流程数据状态
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(actId).includeProcessVariables().singleResult();
        String dataTable = historicProcessInstance.getProcessVariables().get("actDataTable").toString();
        String dataId = historicProcessInstance.getProcessVariables().get("actDataId").toString();
        // 获取流程审批结果是否为不同意
        String approved = historicProcessInstance.getProcessVariables().get("approved") != null ?  historicProcessInstance.getProcessVariables().get("approved").toString() : "";

        String status = this.getActEndStatus(historicProcessInstance.getId());



        // 流程结束后修改流程状态
        if (StringUtils.equals(approved,"不同意") && StringUtils.equals(status,"W")){
            status = "C";
        }
        this.updateEndStatus(dataTable,dataId,status);

        // 正常审批完成后执行的方法
        if ("W".equals(status)){
            if ("wf_bus_node".equals(dataTable)){
                // 推送上会记录
                JSONObject messageJson = new JSONObject();
                messageJson.put("dataId",dataId);
                mqProducer.sendMessageByBeanName("mtBusinessDetailService",dataId);

                // 修改项目进展状态等
                wfBusNodeService.sendEvent(dataId,historicProcessInstance.getName());

                // 判断审批完成后是否应改将项目改完投后阶段，如果是则将项目切换至投后
                this.switchBusStatus(dataId);

                // 判断审批完成后是否跳转一级阶段
                this.jumpStage(dataId);


                Map<String, String> dataTableAndDataId = ActUtils.getDataTableAndDataId(actId);
                dataId = dataTableAndDataId.get("actDataId");
                dataTable = dataTableAndDataId.get("actDataTable");


            }


            // 调用业务功能结束后需要执行的方法
            this.businessEnd(dataTable,dataId,actId,historicProcessInstance.getProcessVariables());
        }

        // 发送流程结束通知
        this.sendProcessEndMessage(historicProcessInstance,status);

        return true;
    }

    /**
     * 跳转业务一级节点
     * @param busId
     */
    public void jumpStage(String busId){
        try {
            WfBusNode wfBusNode = wfBusNodeDao.getById(busId);
            WfConfigNode wfConfigNode = wfConfigNodeDao.getById(wfBusNode.getNodeId());
            if (wfConfigNode != null && StringUtils.isNotBlank(wfConfigNode.getJumpStage())){

                WfBusNodeEvolve wfBusNodeEvolve = wfBusNodeEvolveService.getLatestEvolve(wfBusNode.getBusType(), wfBusNode.getBusId(), wfBusNode.getRoundId());

                WfConfigNode currentNode = wfConfigNodeDao.getById(wfBusNodeEvolve.getNodeId());
                WfConfigNode jumpNode = wfConfigNodeDao.getById(wfConfigNode.getJumpStage());

                if (currentNode != null && jumpNode != null){
                    if (currentNode.getSort() != null && jumpNode.getSort() != null  && jumpNode.getSort() > currentNode.getSort()){
                        WfBusNode nextNode = wfBusNodeService.getByNodeId(wfConfigNode.getJumpStage(),wfBusNode.getBusId());

                        wfBusNodeEvolveService.saveByBusNode(nextNode,wfBusNodeEvolve.getRoundId());

                        // 项目切换阶段时发送提醒
                        wfBusNodeService.sendMessage(wfBusNodeEvolve, nextNode);

                        // 修改业务状态
                        wfBusNodeService.switchBusStatus(nextNode);
                        // 修改项目阶段
                        WfConfigNode wfConfigNodeById = wfConfigNodeDao.getById(nextNode.getNodeId());
                        if ("deal".equals(wfBusNode.getBusType())) {
                            // 如果不是首轮投资则不改状态
                            String roundId = nextNode.getRoundId();
                            if (org.apache.commons.lang3.StringUtils.isNotBlank(roundId)){
                                WfBusRound wfBusRound = wfBusRoundService.get(roundId);
                                if (wfBusRound != null && wfBusRound.getNum() != 1){
                                    return;
                                }
                            }
                            actProcessDao.updateDataTableStage("deal_base", wfBusNode.getBusId(), DictUtils.getDictValue(wfConfigNodeById.getNodeName(),"deal_stage"));
                        }
                    }
                }



            }
        }catch (Exception e){
            LogUtils.error("流程跳转阶段异常",e);
        }

    }

    /**
     * 发送流程审批结束后通知
     * @param historicProcessInstance
     */
    public void sendProcessEndMessage(HistoricProcessInstance historicProcessInstance,String status){
        JSONObject messageJson = new JSONObject();
        messageJson.put("status", DictUtils.getDictLabel(status,"work_flow_status",""));
        messageJson.put("title",historicProcessInstance.getName());
        messageJson.put("consuming", DateUtils.timeStampToDate((System.currentTimeMillis()-historicProcessInstance.getStartTime().getTime())/1000));

        // 组件地址
        messageJson.put("component","@/views/act/process/processInfoForm");
        // 数据ID
        messageJson.put("dataId",historicProcessInstance.getId());

        SysUser startUser = UserUtils.getUserByUserName(historicProcessInstance.getStartUserId());

        SendMessageUtils.sendMessage("processEnd",startUser.getId(),messageJson);
    }

    /**
     * 切换业务状态
     * @param busId wf_bus_node 表ID
     */
    public void switchBusStatus(String busId){
        try {
            WfBusNode wfBusNode = wfBusNodeDao.getById(busId);
            if ("deal".equals(wfBusNode.getBusType())){
                WfConfigNode wfConfigNode = wfConfigNodeDao.getById(wfBusNode.getNodeId());
                if (wfConfigNode != null && "Y".equals(wfConfigNode.getAfter())){
                    List<String> nodeIdList = wfConfigNodeDao.findListByAfter(StringUtils.symbolHandler(wfConfigNode.getFlowId()));
                    for (String nodeId : nodeIdList) {
                        int completeNum = wfBusNodeService.findCompleteByNodeId(nodeId, wfBusNode.getBusId());
                        if (completeNum == 0){
                            return;
                        }
                    }
                    Map<String, SwitchBusStatus> beansMap = context.getBeansOfType(SwitchBusStatus.class);
                    beansMap.get("dealBaseService").switchStatus(wfBusNode.getBusId(), "TH");
                }
            }
        }catch (Exception e){
            LogUtils.error("切换业务状态异常",e);
        }



    }

    /**
     * 调用业务结束后方法
     * @param dataTable 业务表名
     * @param dataId 业务ID
     * @param actId 流程实例ID
     * @param actId 流程变量
     */
    public void businessEnd(String dataTable,String dataId,String actId,Map<String,Object> var){
        Map<String, ProcessEnd> beansMap = context.getBeansOfType(ProcessEnd.class);
        List<String> hiBeanKey = new ArrayList<>();

        for (String beanKey : beansMap.keySet()) {
            if (!hiBeanKey.contains(beanKey)) {
                ProcessEnd processEnd = beansMap.get(beanKey);
                try {
                    processEnd.processEnd(dataTable,dataId,actId);
                }catch (Exception e){
                    LogUtils.error("流程结束后调用方法异常:" + beanKey, e);
                }

                hiBeanKey.add(beanKey);
            }
        }

        // 如果是表单配置的功能则调用表单配置相关代码
        if (var != null){
            if ((var.get("actFormType") != null && "defined".equals(var.get("actFormType").toString())) || "@/views/system/desform/release/onlineView".equals(var.get("actViewPath"))){
                Map<String, Object> map = onlineServer.queryFormData(var.get("actFormId").toString(), dataId);
                JSONObject json = new JSONObject(map);
                // 执行的java代码
                enhanceService.executeEnhanceJava(var.get("actFormId").toString(),var.get("actDataId").toString(),json);
                // 执行 SQL脚本
                enhanceService.executeEnhanceSql(var.get("actFormId").toString(),var.get("actDataId").toString(),json);
            }
        }

    }

}
